﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using App1AppHandler;
using Reborn_WorldServer;
using System.Timers;

namespace Reborn_Server.App1AppHandler
{
    public class Spell_LifeFunnel : Buff
    {
        public Spell_LifeFunnel() 
        {
            //2 second ticks
            spellTimer.Interval = 2000;

            //Display "?" to player for duration
            minutesLeft = -2;
        }

        //Life Funnel (healthtap DOT) 300 Damage 
        private int BaseDamage = 33;
        private int BaseTicksStart = 9;

        private int CalcDotDamage = 0;

        public void Cast(CreatureBase myCreatureBase, int CastLevel, long CreatureGUID)
        {
            List<MapItem> MapItemsWithin12;
            if (base.InitializeCast(myCreatureBase, CastLevel, CreatureGUID, true, out MapItemsWithin12) == false)
                return;

            ticksLeft = BaseTicksStart;
            int DotAmount = BaseDamage * ticksLeft;

            DotAmount = SkillManager.AdjustForCombat(CastLevel, DotAmount, myCreatureBase.IntelligenceTotal);
            DotAmount = TargetCreatureBase.CalculateGetSpellDamagePerResists(DotAmount, base.spellIcon.Skill);

            CalcDotDamage = DotAmount / ticksLeft;

            foreach (MapItem mapitem in MapItemsWithin12)
            {
                foreach (CreatureBase creaturebase in mapitem.CreaturesBases)
                {
                    if (creaturebase is Character)
                    {
                        Character character = (Character)creaturebase;
                        character.PlaySound("Necrosis", TargetCreatureBase.MapX, TargetCreatureBase.MapY);
                    }
                }
            }

            TargetCreatureBase.buffManager.UpdateBuffs();

            //Now we need to put the beneficial buff on the caster.
            Spell_LifeFunnel lifeFunnelHealBuff = new Spell_LifeFunnel();
            lifeFunnelHealBuff.CalcDotDamage = CalcDotDamage;
            
            SpellIcon lifeFunnelHealIcon = spellIcon.clone();
            lifeFunnelHealIcon.Offensive = false;

            //Make sure we cannot stack the heal buff.
            foreach (Buff buff in myCreatureBase.buffManager.Buffs)
            {
                if (buff.spellIcon.StackType == lifeFunnelHealIcon.StackType &&
                    buff.spellIcon.Offensive == lifeFunnelHealIcon.Offensive)
                {
                    buff.RemoveSpell(false, false);
                    break;
                }
            }
            //Resuming this spell with optional value = negative CalcDamage will turn it into a heal buff.
            lifeFunnelHealBuff.Resume(myCreatureBase, lifeFunnelHealIcon, ticksLeft, CastingCreatureLevel, CastingCharacterID, CastingCreatureInt, CastingCreatureWis, CalcDotDamage * -1, null);
            
            myCreatureBase.buffManager.UpdateBuffs();

            //Resume does not automatically update client creature base (to update buffs). Send out this update.
            foreach (MapItem mapitem in MapItemsWithin12)
            {
                if (Math.Abs(mapitem.MapX - myCreatureBase.MapX) <= 4 && Math.Abs(mapitem.MapY - myCreatureBase.MapY) <= 4)
                {
                    foreach (CreatureBase creatureBase in mapitem.CreaturesBases)
                    {
                        if (creatureBase is Character)
                        {
                            Character charactertoupdate = (Character)creatureBase;
                            charactertoupdate.AddCreatureBase(myCreatureBase);
                        }
                    }
                }
            }

            spellTimer.Start();
        }

        //Optional value = calcDamage (we wont have the target when this resumes so we have to store the calculated damage)
        //value will be negative for heal, positive for damage
        public override int GetOptionalValue()
        {
            if (spellIcon.Offensive == true)
                return CalcDotDamage;
            return CalcDotDamage * -1;
        }

        public override void Resume(CreatureBase targetCreatureBase, SpellIcon _spellIcon, int timeRemaining, int castLevel, int castCharacterID, int castInt, int castWis, int optionalValue, string xmlData)
        {
            //Copy the spell icon because we may change properties.
            _spellIcon = _spellIcon.clone();

            //Is heal version
            if (optionalValue < 0)
                _spellIcon.Offensive = false;
            //Is Dot version
            else
                _spellIcon.Offensive = true;

            if (optionalValue < 0)
                optionalValue = optionalValue * -1;

            CalcDotDamage = optionalValue;

            ticksLeft = timeRemaining;
            base.Resume(targetCreatureBase, _spellIcon, timeRemaining, castLevel, castCharacterID, castInt, castWis, optionalValue, xmlData);

            spellTimer.Start();
        }

        public override void RemoveSpell(bool updateBuffs, bool sendMessage)
        {
            //Dont let the base send messages (it will duplicate because we have 2 spells running, 
            //One for caster, one for target. The base will send a message to both.
            base.RemoveSpell(updateBuffs, false);

            if (sendMessage == true)
                TargetCreatureBase.SendMessage(base.spellIcon.Name + " has worn off you", "spelldefense");
        }

        protected override void SpellTimer_Expired(object source, ElapsedEventArgs e)
        {
            LockItem lockitem = TargetCreatureBase.GameHandler.GetLockItem(TargetCreatureBase.MapID, TargetCreatureBase.Instance);

            lock (lockitem.LockObj)
            {
                //This buff has been removed, do nothing (this can occur if the buff gets overwritten exactly when this timer fires)
                if (TargetCreatureBase.buffManager.hasBuff(this.SpellID) == false)
                    return;

                if (TargetCreatureBase.HP < 1)
                {
                    RemoveSpell(true, false);
                    return;
                }

                Map CurrentMap = TargetCreatureBase.GameHandler.GetMap(TargetCreatureBase.MapID, TargetCreatureBase.Instance);
                List<MapItem> MapItemsWithin8 = new List<MapItem>();
                List<Character> CharactersWithin8 = new List<Character>();
                MapItem CurrentMapItem = null;
                foreach (MapItem mapitem in CurrentMap.MapItems)
                {
                    if (Math.Abs(mapitem.MapX - TargetCreatureBase.MapX) <= 8 && Math.Abs(mapitem.MapY - TargetCreatureBase.MapY) <= 8)
                    {
                        MapItemsWithin8.Add(mapitem);
                        foreach (CreatureBase creaturebase in mapitem.CreaturesBases)
                        {
                            if (creaturebase is Character)
                                CharactersWithin8.Add((Character)creaturebase);
                        }
                    }
                    if (mapitem.MapX == TargetCreatureBase.MapX && mapitem.MapY == TargetCreatureBase.MapY)
                        CurrentMapItem = mapitem;
                }

                int absorbedDamage = 0;
                if (spellIcon.Offensive == true)
                    TargetCreatureBase.InflictSpellDamage(CalcDotDamage, CastingCharacterID, CastingCreatureGUID, spellIcon.Skill, out absorbedDamage);
                else
                    TargetCreatureBase.HP = TargetCreatureBase.HP + CalcDotDamage;

                TargetCreatureBase.Update_Character();

                int actualDamage = CalcDotDamage - absorbedDamage;

                //We only need to possibly send message to the target because there are actually 2 spells being used, other version the caster will be the target.
                if(spellIcon.Offensive == false)
                {
                    TargetCreatureBase.SendMessage("You health funnel heals you! " + "(" + actualDamage.ToString() + ")","spelldamage");
                }
                else if (spellIcon.Offensive == true)
                {
                    if (absorbedDamage != 0)
                        TargetCreatureBase.SendMessage("Your health is draining! (" + actualDamage.ToString() + ") ABSORBED " + absorbedDamage.ToString(),"spelldamaged");
                    else
                        TargetCreatureBase.SendMessage("Your health is draining! (" + actualDamage.ToString() + ")" ,"spelldamaged");
                }

                if (TargetCreatureBase.HP < 1 && spellIcon.Offensive == true)
                {
                    if (!(TargetCreatureBase is Character))
                        CurrentMapItem.CreaturesBases.Remove(TargetCreatureBase);

                    TargetCreatureBase.SendMessage("You have been slain!", "slain");

                    if (!(TargetCreatureBase is Character && TargetCreatureBase.ID == CastingCharacterID))
                        Managers.GameHandler.TrySendMessage(CastingCharacterID, "You have slain " + TargetCreatureBase.Name + "!", "slay");

                    foreach (Character character in CharactersWithin8)
                    {
                        if (Math.Abs(character.MapX - TargetCreatureBase.MapX) <= 4 && Math.Abs(character.MapY - TargetCreatureBase.MapY) <= 4)
                            character.AddMapItem(CurrentMapItem);
                    }

                    //This spell killed the creature so this buff has already been removed, do nothing.
                    return;
                }
                else
                {
                    foreach (Character character in CharactersWithin8)
                    {
                        if (Math.Abs(character.MapX - TargetCreatureBase.MapX) <= 4 && Math.Abs(character.MapY - TargetCreatureBase.MapY) <= 4)
                            character.UpdateCreatureBaseHp(TargetCreatureBase);
                    }
                }
                if (ticksLeft > 0)
                {
                    ticksLeft--;
                    spellTimer.Start();
                }
                else
                    RemoveSpell(true, true);
            }
        }
    }
}
